package cn.talk.doodle.dialog;

import cn.talk.doodle.util.DensityUtils;
import ohos.agp.components.Component;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

public class ColorPickerView extends Component implements Component.DrawTask,Component.EstimateSizeListener, Component.TouchEventListener {

    private Paint mPaint;//渐变色环画笔
    private Paint mCenterPaint;//中间圆画笔
    private Paint mLinePaint;//分隔线画笔
    private Paint mRectPaint;//渐变方块画笔

    private Shader rectShader;//渐变方块渐变图像
    private float rectLeft;//渐变方块左x坐标
    private float rectTop;//渐变方块右x坐标
    private float rectRight;//渐变方块上y坐标
    private float rectBottom;//渐变方块下y坐标

    private  Color[] mCircleColors;//渐变色环颜色
    private  Color[] mRectColors;//渐变方块颜色

    private int mHeight;//View高
    private int mWidth;//View宽
    private float r;//色环半径(paint中部)
    private float centerRadius;//中心圆半径

    private boolean downInCircle = true;//按在渐变环上
    private boolean downInRect;//按在渐变方块上
    private boolean highlightCenter;//高亮
    private boolean highlightCenterLittle;//微亮
    private RectFloat mRectF;
    private OnSelectedColorListener mOnSelectedColorListener;

    public ColorPickerView(Context context, Color initColor, int height, int width, OnSelectedColorListener listener) {
        super(context);
        this.mHeight = height;
        this.mWidth = width;
        setMinWidth(width);
        setMinHeight(height);
        //渐变色环参数
        mCircleColors = new Color[]{new Color(0xFFFF0000), new Color(0xFFFF00FF), new Color(0xFF0000FF),
                new Color(0xFF00FFFF), new Color(0xFF00FF00), new Color(0xFFFFFF00), new Color(0xFFFF0000)};
        Shader s=new SweepShader(0,0,mCircleColors, null);
        mPaint = new Paint();
        mPaint.setShader(s, Paint.ShaderType.SWEEP_SHADER);
        mPaint.setStyle(Paint.Style.STROKE_STYLE);
        mPaint.setStrokeWidth(DensityUtils.vp2px(context, 30));//圆环大小
        r = width / 2 * 0.7f - mPaint.getStrokeWidth() * 0.5f;

        //中心圆参数
        mCenterPaint = new Paint();
        mCenterPaint.setColor(initColor);
        mCenterPaint.setStrokeWidth(5);
        centerRadius = (r - mPaint.getStrokeWidth() / 2) * 0.7f;

        //边框参数
        mLinePaint = new Paint();
        mLinePaint.setColor(new Color(Color.getIntColor("#72A1D1")));
        mLinePaint.setStrokeWidth(4);

        //黑白渐变参数
        mRectColors = new Color[]{new Color(0xFF000000), mCenterPaint.getColor(), new Color(0xFFFFFFFF)};
        mRectPaint = new Paint();
        mRectPaint.setStrokeWidth(DensityUtils.vp2px(context, 5));
        rectLeft = -r - mPaint.getStrokeWidth() * 0.5f;
        rectTop = r + mPaint.getStrokeWidth() * 0.5f +
                mLinePaint.getAngle() * 0.5f + 15;
        rectRight = r + mPaint.getStrokeWidth() * 0.5f;
        rectBottom = rectTop + DensityUtils.vp2px(context, 30);

        mOnSelectedColorListener = listener;
    }

    private PixelMapElement mDrawable;
    private PixelMapShader mBitmapShader;

    public void setDrawable(PixelMapElement drawable) {
        mDrawable = drawable;
        PixelMapShader
        mBitmapShader = new PixelMapShader(new PixelMapHolder(drawable.getPixelMap()), Shader.TileMode.MIRROR_TILEMODE, Shader.TileMode.MIRROR_TILEMODE);
        invalidate();
    }

    public PixelMapElement getDrawable() {
        return mDrawable;
    }


    @Override
    public void onDraw(Component component, Canvas canvas) {
        //移动中心
        canvas.translate(mWidth / 2, mHeight / 2 - 50);
        if (mDrawable != null) {
            mCenterPaint.setShader(mBitmapShader, Paint.ShaderType.PIXELMAP_SHADER);
        } else {
            mCenterPaint.setShader(null,null);
        }
        //画中心圆
        canvas.drawCircle(0, 0, centerRadius, mCenterPaint);
        //是否显示中心圆外的小圆环
        if (highlightCenter || highlightCenterLittle) {
            Color c = mCenterPaint.getColor();
            mCenterPaint.setStyle(Paint.Style.STROKE_STYLE);
            if (highlightCenter) {
                mCenterPaint.setAlpha(0xFF);
            } else if (highlightCenterLittle) {
                mCenterPaint.setAlpha(0x90);
            }
            canvas.drawCircle(0, 0,
                    centerRadius + mCenterPaint.getStrokeWidth(), mCenterPaint);

            mCenterPaint.setStyle(Paint.Style.FILL_STYLE);
            mCenterPaint.setColor(c);
        }

        mRectF=new RectFloat(-r,-r,r,r);

        //画色环
        canvas.drawOval(mRectF, mPaint);
        //画黑白渐变块
        Point point= new Point(rectLeft,rectRight);
        Point[] points=new Point[1];
        points[0]=point;
        if (downInCircle) {
            if (mRectColors[1] != mCenterPaint.getColor()) {
                mRectColors[1] = mCenterPaint.getColor();
                rectShader = new LinearShader(points, null, mRectColors, Shader.TileMode.MIRROR_TILEMODE);
            }
        }
        if (rectShader == null) {
            rectShader = new LinearShader(points, null, mRectColors, Shader.TileMode.MIRROR_TILEMODE);
        }

        mRectPaint.setShader(rectShader, Paint.ShaderType.LINEAR_SHADER);
        canvas.drawRect(rectLeft, rectTop, rectRight, rectBottom, mRectPaint);
        float offset = mLinePaint.getStrokeWidth() / 2;
        canvas.drawLine(rectLeft - offset, rectTop - offset * 2,
                rectLeft - offset, rectBottom + offset * 2, mLinePaint);//左
        canvas.drawLine(rectLeft - offset * 2, rectTop - offset,
                rectRight + offset * 2, rectTop - offset, mLinePaint);//上
        canvas.drawLine(rectRight + offset, rectTop - offset * 2,
                rectRight + offset, rectBottom + offset * 2, mLinePaint);//右
        canvas.drawLine(rectLeft - offset * 2, rectBottom + offset,
                rectRight + offset * 2, rectBottom + offset, mLinePaint);//下

    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        float x = event.getPointerPosition(0).getX() - mWidth / 2;
        float y = event.getPointerPosition(0).getY() - mHeight / 2 + 50;
        boolean inCircle = inColorCircle(x, y,
                r + mPaint.getStrokeWidth() / 2, r - mPaint.getStrokeWidth() / 2);
        boolean inCenter = inCenter(x, y, centerRadius);
        boolean inRect = inRect(x, y);

        switch (event.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                downInCircle = inCircle;
                downInRect = inRect;
                highlightCenter = inCenter;
            case TouchEvent.POINT_MOVE:
                if (downInCircle && inCircle) {//down按在渐变色环内, 且move也在渐变色环内
                    float angle = (float) Math.atan2(y, x);
                    float unit = (float) (angle / (2 * Math.PI));
                    if (unit < 0) {
                        unit += 1;
                    }
                    mDrawable = null;
                    mCenterPaint.setColor(interpCircleColor(mCircleColors, unit));
                } else if (downInRect && inRect) {//down在渐变方块内, 且move也在渐变方块内
                    mDrawable = null;
                    mCenterPaint.setColor(interpRectColor(mRectColors, x));
                }
                if ((highlightCenter && inCenter) || (highlightCenterLittle && inCenter)) {//点击中心圆, 当前移动在中心圆
                    highlightCenter = true;
                    highlightCenterLittle = false;
                } else if (highlightCenter || highlightCenterLittle) {//点击在中心圆, 当前移出中心圆
                    highlightCenter = false;
                    highlightCenterLittle = true;
                } else {
                    highlightCenter = false;
                    highlightCenterLittle = false;
                }
                invalidate();
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                if (highlightCenter && inCenter) {//点击在中心圆, 且当前启动在中心圆
                    if (mOnSelectedColorListener != null) {
                        mOnSelectedColorListener.onSelected(mCenterPaint.getColor());
                    }
                }
                if (downInCircle) {
                    downInCircle = false;
                }
                if (downInRect) {
                    downInRect = false;
                }
                if (highlightCenter) {
                    highlightCenter = false;
                }
                if (highlightCenterLittle) {
                    highlightCenterLittle = false;
                }
                invalidate();
                break;
        }
        return true;
    }

    @Override
    public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
        setEstimatedSize(
                Component.EstimateSpec.getChildSizeWithMode(mWidth, mWidth, Component.EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(mHeight, mHeight, Component.EstimateSpec.NOT_EXCEED));
        return true;
    }

    /**
     * 坐标是否在色环上
     *
     * @param x         坐标
     * @param y         坐标
     * @param outRadius 色环外半径
     * @param inRadius  色环内半径
     * @return
     */
    private boolean inColorCircle(float x, float y, float outRadius, float inRadius) {
        double outCircle = Math.PI * outRadius * outRadius;
        double inCircle = Math.PI * inRadius * inRadius;
        double fingerCircle = Math.PI * (x * x + y * y);
        return fingerCircle < outCircle && fingerCircle > inCircle;
    }

    /**
     * 坐标是否在中心圆上
     *
     * @param x            坐标
     * @param y            坐标
     * @param centerRadius 圆半径
     * @return
     */
    private boolean inCenter(float x, float y, float centerRadius) {
        double centerCircle = Math.PI * centerRadius * centerRadius;
        double fingerCircle = Math.PI * (x * x + y * y);
        return fingerCircle < centerCircle;
    }

    /**
     * 坐标是否在渐变色中
     *
     * @param x
     * @param y
     * @return
     */
    private boolean inRect(float x, float y) {
        return x <= rectRight && x >= rectLeft && y <= rectBottom && y >= rectTop;
    }

    /**
     * 获取圆环上颜色
     *
     * @param colors
     * @param unit
     * @return
     */
    private Color interpCircleColor(Color colors[], float unit) {
        if (unit <= 0) {
            return colors[0];
        }
        if (unit >= 1) {
            return colors[colors.length - 1];
        }

        float p = unit * (colors.length - 1);
        int i = (int) p;
        p -= i;

        // now p is just the fractional part [0...1) and i is the index
        int c0 = colors[i].getValue();
        int c1 = colors[i + 1].getValue();
        int a = ave(Color.alpha(c0), Color.alpha(c1), p);
//        int r = ave(Color.red(c0), Color.red(c1), p);
//        int g = ave(Color.green(c0), Color.green(c1), p);
//        int b = ave(Color.blue(c0), Color.blue(c1), p);
//
//        return Color.argb(a, r, g, b);
        return new Color(a);
    }

    /**
     * 获取渐变块上颜色
     *
     * @param colors
     * @param x
     * @return
     */
    private Color interpRectColor(Color colors[], float x) {
        int a, r, g, b, c0, c1;
        float p;
        if (x < 0) {
            c0 = colors[0].getValue();
            c1 = colors[1].getValue();
            p = (x + rectRight) / rectRight;
        } else {
            c0 = colors[1].getValue();
            c1 = colors[2].getValue();
            p = x / rectRight;
        }
        a = ave(Color.alpha(c0), Color.alpha(c1), p);
//        r = ave(Color.red(c0), Color.red(c1), p);
//        g = ave(Color.green(c0), Color.green(c1), p);
//        b = ave(Color.blue(c0), Color.blue(c1), p);
        return new Color(a);
    }

    private int ave(int s, int d, float p) {
        return s + Math.round(p * (d - s));
    }

    public void setColor(int color) {
        mCenterPaint.setColor(new Color(color));
        mRectColors[1] = mCenterPaint.getColor();
    }

    public Color getColor() {
        return mCenterPaint.getColor();
    }


    public interface OnSelectedColorListener {
        void onSelected(Color color);
    }

}
